package cn.iocoder.an.module.mold.service.equipmnetkeepwait;

import cn.iocoder.an.framework.common.pojo.PageResult;
import cn.iocoder.an.framework.common.util.business.CreateKeepNo;
import cn.iocoder.an.framework.common.util.object.BeanUtils;
import cn.iocoder.an.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.an.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.an.module.business.dal.dataobject.equipmentmanage.EquipmentManageDO;
import cn.iocoder.an.module.business.dal.mysql.equipmentmanage.EquipmentManageMapper;
import cn.iocoder.an.module.business.service.equipmentmanage.EquipmentManageService;
import cn.iocoder.an.module.mold.controller.admin.equipmnetkeepwait.vo.EquipmnetKeepWaitPageReqVO;
import cn.iocoder.an.module.mold.controller.admin.equipmnetkeepwait.vo.EquipmnetKeepWaitSaveReqVO;
import cn.iocoder.an.module.mold.dal.dataobject.equipmnetkeepwait.EquipmnetKeepWaitDO;
import cn.iocoder.an.module.mold.dal.mysql.equipmnetkeepwait.EquipmnetKeepWaitMapper;
import cn.iocoder.an.module.mold.enums.KeepStatusEnum;
import cn.iocoder.an.module.business.utils.WeComMessageUtil;
import cn.iocoder.an.module.system.api.notify.NotifyMessageSendApi;
import cn.iocoder.an.module.system.api.notify.dto.NotifySendSingleToUserReqDTO;
import cn.iocoder.an.module.system.dal.dataobject.dict.DictDataDO;
import cn.iocoder.an.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.an.module.system.service.dict.DictDataService;
import cn.iocoder.an.module.system.service.permission.PermissionService;
import cn.iocoder.an.module.system.service.user.AdminUserService;
import jakarta.annotation.Resource;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static cn.iocoder.an.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.an.module.business.enums.ErrorCodeConstants.EQUIPMNET_KEEP_WAIT_NOT_EXISTS;

/**
 * 待保养设备 Service 实现类
 *
 * @author zzy
 */
@Service("EquipmnetKeepWaitServiceImplDamage")
@Validated
public class EquipmnetKeepWaitServiceImpl implements EquipmnetKeepWaitService {

    @Autowired
    private EquipmnetKeepWaitMapper equipmnetKeepWaitMapper;

    @Autowired
    private AdminUserService userService;

    @Autowired
    private WeComMessageUtil weComMessageUtil;

    @Autowired
    private NotifyMessageSendApi notifySendApi;

    @Autowired
    private PermissionService permissionService;

    @Autowired
    private DictDataService dictDataService;

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private EquipmentManageMapper equipmentManageMapper;

    @Autowired
    private EquipmentManageService equipmentManageService;


    public void createEquipmnetKeepWait(EquipmnetKeepWaitSaveReqVO createReqVO) {

        // 当前年月，用于单号前缀
        String yearMonth = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMM"));
        String prefix = CreateKeepNo.PREFIXWH; // "BY"
        String prefixPattern = prefix + yearMonth; // "BY202508"

        // 🔐 分布式锁 key：按月隔离，不同月不互斥
        String lockKey = "lock:keep_no:" + prefixPattern;
        RLock lock = redissonClient.getLock(lockKey);

        try {
            // 获取锁（最多等待10秒，持有30秒自动释放）
            boolean isLocked = lock.tryLock(10, 30, TimeUnit.SECONDS);
            if (!isLocked) {
                throw new RuntimeException("获取分布式锁失败，无法生成唯一单号");
            }

            // ✅ 在锁内查询当前最大单号
            String maxKeepNo = equipmnetKeepWaitMapper.findMaxKeepNo(prefixPattern);

            // ✅ 生成下一个基础单号（如 BY2025080001）
            String nextBaseNo = CreateKeepNo.generateNextCode(maxKeepNo);

            List<EquipmnetKeepWaitDO> saveList = new ArrayList<>();

            // 按设备：单个设备
            EquipmentManageDO equipment = equipmentManageMapper.selectById(createReqVO.getEquipmentId());
            if (equipment == null) {
                return;
            }

            if (equipment.getMaintainDatetime() == null) {

            }


            EquipmnetKeepWaitDO save = new EquipmnetKeepWaitDO();


            //保养人自动设置为上次保养的人 查询最近一条 改  取设备的维护人员
//            LambdaQueryWrapperX<EquipmnetKeepWaitDO> waitWrapperE = new LambdaQueryWrapperX<>();
//            waitWrapperE.eq(EquipmnetKeepWaitDO::getEquipmentId, equipment.getId());
//            waitWrapperE.isNotNull(EquipmnetKeepWaitDO::getDutyUserId);
//            waitWrapperE.orderByDesc(EquipmnetKeepWaitDO::getUpdateTime);
//            waitWrapperE.last("limit 1");
//            EquipmnetKeepWaitDO keepWaitDO = equipmnetKeepWaitMapper.selectOne(waitWrapperE);
//            if (keepWaitDO != null) {
//                save.setDutyUserId(keepWaitDO.getDutyUserId());
//            }

            save.setDutyUserId(equipment.getMaintenanceUserIdDamage());

            save.setKeepNo(nextBaseNo); // 直接使用生成的第一个号
            save.setItemId(createReqVO.getItemId());
            save.setEquipmentId(equipment.getId());
            save.setStatus(KeepStatusEnum.WAIT.getKeepStatus());
            save.setEquipmentName(equipment.getEquipmentName());
            save.setPlanDate(createReqVO.getPlanDate());
            saveList.add(save);

            // 批量插入（事务内）
            if (!saveList.isEmpty()) {
                equipmnetKeepWaitMapper.insertBatch(saveList);
            }

        } catch (
                InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException("生成单号时被中断", e);
        } catch (
                Exception e) {
            throw new RuntimeException("生成保养任务失败: " + e.getMessage(), e);
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    @Override
    public void updateEquipmnetKeepWait(EquipmnetKeepWaitSaveReqVO updateReqVO) {
        // 校验存在
        validateEquipmnetKeepWaitExists(updateReqVO.getId());

        if (updateReqVO.getStatus() == 10) {
            //说明是派工操作
            //设置责任人 派工时间 并推送消息  更新设备台账的维护人员
            List<Long> dutyUserId = updateReqVO.getDutyUserId();
            List<AdminUserDO> userList = userService.getUserList(dutyUserId);
            String dutyUserName = userList.stream()
                    .map(AdminUserDO::getNickname)                    // 提取 nickname
                    .filter(nickname -> nickname != null && !nickname.trim().isEmpty()) // 过滤 null/空
                    .collect(Collectors.joining(","));               // 用逗号拼接
            updateReqVO.setDutyUserName(dutyUserName);
            //设置当前时间为派工时间
            updateReqVO.setSendTime(LocalDateTime.now());
            //消息推送
            sendKeepMessage(dutyUserId);

            // 更新设备台账的维护人员
            Long equipmentId = updateReqVO.getEquipmentId();
            EquipmentManageDO equipmentManageDO = equipmentManageMapper.selectById(equipmentId);
            equipmentManageDO.setMaintenanceUserIdDamage(dutyUserId);
            equipmentManageService.updateEquipmentManageByDo(equipmentManageDO);

        }

        // 更新
        EquipmnetKeepWaitDO updateObj = BeanUtils.toBean(updateReqVO, EquipmnetKeepWaitDO.class);
        equipmnetKeepWaitMapper.updateById(updateObj);

    }

    public void sendKeepMessage(List<Long> dutyUserId) {
        //推送消息
        List<AdminUserDO> userList = userService.getUserList(dutyUserId);
        String userIds = "";
        StringBuilder userIdBuilder = new StringBuilder();

        // 获取当前时间并格式化
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String formattedNow = now.format(formatter);

        for (AdminUserDO user : userList) {
            // 1. 推送系统消息 准备参数
            String templateCode = "by-6"; // 站内信模版，记得在【站内信管理】中配置噢
            Map<String, Object> templateParams = new HashMap<>();
            templateParams.put("time", formattedNow);
            NotifySendSingleToUserReqDTO sendToUserDTO = new NotifySendSingleToUserReqDTO();
            sendToUserDTO.setUserId(user.getId());
            sendToUserDTO.setTemplateCode(templateCode);
            sendToUserDTO.setTemplateParams(templateParams);
            Long l = notifySendApi.sendSingleMessageToAdmin(sendToUserDTO);
            System.out.printf("系统内消息通知:", l);

            String userId = weComMessageUtil.getUserIdByMobile(user.getEnterpriseWeChatAccount());
            if (userId != null && !userId.trim().isEmpty()) {
                // 如果已经有内容了，先添加分隔符
                if (userIdBuilder.length() > 0) {
                    userIdBuilder.append("|");
                }
                userIdBuilder.append(userId);
            }
        }

        // 将 StringBuilder 转换为最终的字符串
        userIds = userIdBuilder.toString();
        // 可选：检查最终结果是否为空
        if (userIds.isEmpty()) {
            // 处理没有找到任何有效用户ID的情况
            System.out.printf("没有找到任何有效的企业微信 UserID");
            return;
        }

        // 1. 使用 sendTextMessage 方法 (更灵活，可以同时指定用户、部门、标签)

        //从字典配置中获取发送的消息
        DictDataDO wxMessage = dictDataService.getDictData("by_message", "5");
        String systemMessage = wxMessage.getLabel() + formattedNow;
        // 将时间戳添加到消息中
        WeComMessageUtil.WeComSendResult weComSendResult = weComMessageUtil.sendTextMessage(systemMessage, userIds, null, null);
        System.out.printf("推送结果:" + weComSendResult.toString());

    }


    @Override
    public void deleteEquipmnetKeepWait(Long id) {
        // 校验存在
        validateEquipmnetKeepWaitExists(id);
        // 删除
        equipmnetKeepWaitMapper.deleteById(id);
    }

    @Override
    public void deleteEquipmnetKeepWaitListByIds(List<Long> ids) {
        // 删除
        equipmnetKeepWaitMapper.deleteByIds(ids);
    }


    private void validateEquipmnetKeepWaitExists(Long id) {
        if (equipmnetKeepWaitMapper.selectById(id) == null) {
            throw exception(EQUIPMNET_KEEP_WAIT_NOT_EXISTS);
        }
    }

    @Override
    public EquipmnetKeepWaitDO getEquipmnetKeepWait(Long id) {
        return equipmnetKeepWaitMapper.selectById(id);
    }

    @Override
    public PageResult<EquipmnetKeepWaitDO> getEquipmnetKeepWaitPage(EquipmnetKeepWaitPageReqVO pageReqVO) {
        //参与的维修申请单或任务单
        List<Long> ids = new ArrayList<>();
        if (pageReqVO.getInstallPosition() != null || pageReqVO.getCode() != null) {
            LambdaQueryWrapperX<EquipmentManageDO> queryWrapperX = new LambdaQueryWrapperX<>();
            queryWrapperX.select(EquipmentManageDO::getId);
            queryWrapperX.likeIfPresent(EquipmentManageDO::getInstallPosition, pageReqVO.getInstallPosition());
            queryWrapperX.likeIfPresent(EquipmentManageDO::getCode, pageReqVO.getCode());


            // selectObjs 返回 List<Object>
            List<Object> objects = equipmentManageMapper.selectObjs(queryWrapperX);
            ids = objects.stream()
                    .map(obj -> ((Number) obj).longValue()) // 安全转 Long
                    .collect(Collectors.toList());
            if (!ids.isEmpty()) {
                pageReqVO.setIdList(ids);
            }
        }


        //1.查询出当前登录人是派工人的或者是保养人创建人所有的待保养ID
        Long currentUserId = SecurityFrameworkUtils.getLoginUserId();
        if (permissionService.hasAnyRoles(SecurityFrameworkUtils.getLoginUserId(), "super_admin", "tenant_admin")) {//判断是不是管理员


        } else {

            /*
            List<Object> requestIdObjects = equipmnetKeepWaitMapper.selectObjs(
                    new QueryWrapper<EquipmnetKeepWaitDO>()
                            .select("id")
                            .apply("JSON_CONTAINS(duty_user_id, CAST({0} AS JSON))", "[" + currentUserId + "]")
                            .or()
                            .eq("duty_user_id", currentUserId)
                            .or()
                            .eq("creator", currentUserId)
            );

            // 转换为 List<Long>
            List<Long> requestIds = requestIdObjects.stream()
                    .map(obj -> (Long) obj)
                    .collect(Collectors.toList());

            Set<Long> uniqueIds = new HashSet<>();
            uniqueIds.addAll(requestIds);

            // 如果需要返回 List
            List<Long> combinedIds = new ArrayList<>(uniqueIds);
            pageReqVO.setIds(combinedIds);
            if (CollectionUtils.isEmpty(combinedIds)) {
                return PageResult.empty(); // 提前返回空列表，避免执行 SQL
            }

             */

        }

        //判断如果日期为空 设置一个默认值  默认查询截至到今天的
        LocalDate[] planDate = pageReqVO.getPlanDate();

        // 防空判断
        if (planDate == null || planDate.length < 2) {
            // 可选：初始化数组
            planDate = new LocalDate[2];
        }

        // 如果开始日期为空，默认设为 2025-01-01
        if (planDate[0] == null || planDate[1] == null) {
            planDate[0] = LocalDate.of(2025, 1, 1);
            planDate[1] = LocalDate.now();
            pageReqVO.setPlanDate(planDate);
        }
        return equipmnetKeepWaitMapper.selectPage(pageReqVO);
    }

}